package main

import (
	"bytes"
	"context"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/AsGz/httpAuthClient"
	"github.com/gin-gonic/gin"
	"github.com/tidwall/gjson"
	"io"
	"io/ioutil"
	"iot-base/common/cache"
	"iot-base/common/ctrltype"
	"iot-base/common/logger"
	"iot-base/common/notify"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"os"
	"strings"
	"time"
)

const (
	//此处用于定义该类型的品牌定义
	HaiKBrand          = "Haik"
	AES128             = 1
	AES256             = 2
	HaiKAddPersonUrl   = "/ISAPI/AccessControl/UserInfo/Record?format=json"
	HaiKDelPersonUrl   = "/ISAPI/AccessControl/UserInfo/Delete?format=json"
	HaiKQueryPersonUrl = "/ISAPI/AccessControl/UserInfo/Search?format=json"
	HaiKInsertCardUrl  = "/ISAPI/AccessControl/CardInfo/Record?format=json"
	HaiKDelCardUrl     = "/ISAPI/AccessControl/CardInfo/Delete?format=json"
	HaiKQueryCardUrl   = "/ISAPI/AccessControl/CardInfo/Search?format=json"
	HaiKPicture        = "/ISAPI/Intelligent/FDLib/FDSetUp?format=json"
	HaiKOpenDoor       = "/ISAPI/AccessControl/RemoteControl/door/1"
	HaiKCloseDoor      = "/ISAPI/AccessControl/RemoteControl/door/1"
)

const (
	GET  = "GET"
	PUT  = "PUT"
	POST = "POST"
)

type HaiKClient struct {
	DoorControl
}

func (d *HaiKClient) Order(pCmd *ctrltype.CtrlCmd) (map[string]interface{}, error) {
	switch pCmd.ID {
	case addPerson:
		return d.insertPerson(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case delPerson:
		return d.delPerson(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case queryPerson:
		return d.queryPerson(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case addCard:
		return d.insertCard(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case delCard:
		return d.delCard(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case queryCard:
		return d.queryCard(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case openDoor:
		return d.open(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	case closeDoor:
		return d.close(pCmd.ThingID, pCmd.Params, pCmd.ArrayParams)
	default:
		return nil, errors.New("no this order")
	}
}

func NewHaiKClient() HaiKClient {
	return HaiKClient{}
}

type haiKPerson struct {
	EmployeeNo      string      `json:"employeeNo"`
	Name            string      `json:"name"`
	UserType        string      `json:"userType"`
	Gender          string      `json:"gender"`
	LocalUIRight    bool        `json:"localUIRight"`
	MaxOpenDoorTime int         `json:"maxOpenDoorTime"`
	Valid           valid       `json:"Valid"`
	DoorRight       string      `json:"doorRight"`
	RightPlan       []rightPlan `json:"RightPlan"`
	UserVerifyMode  string      `json:"userVerifyMode"` //cardOrfaceOrPw#刷卡或人脸或密码
}

type valid struct {
	Enable    bool   `json:"enable"`
	BeginTime string `json:"beginTime"`
	EndTime   string `json:"endTime"`
	TimeType  string `json:"timeType"`
}

type rightPlan struct {
	DoorNo         int    `json:"doorNo"`
	PlanTemplateNo string `json:"planTemplateNo"`
}

type HaiKAddPerson struct {
	AddPerson haiKPerson `json:"UserInfo"`
}

func (d *HaiKClient) insertPerson(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	if len(arrayParams) == 0 {
		return nil, errors.New("无参数输入")
	}
	for _, param := range arrayParams {
		HaiKParamsInfo := NewHaiKParams(param)
		ty, err := HaiKParamsInfo.GetInt8("type")
		if err != nil {
			return nil, err
		}
		code, err := HaiKParamsInfo.GetStr("code")
		if err != nil {
			return nil, err
		}
		name, err := HaiKParamsInfo.GetStr("name")
		if err != nil {
			return nil, err
		}
		sex, err := HaiKParamsInfo.GetStr("sex")
		if err != nil {
			return nil, err
		}
		img, err := HaiKParamsInfo.GetStr("image")
		if err != nil {
			return nil, err
		}
		var uty string
		uty, err = decodePersonType(ty)
		if err != nil {
			return nil, err
		}
		beginTime := time.Now().Format("2006-01-02T15:04:05")
		endTime := time.Now().Add(87600 * time.Hour).Format("2006-01-02T15:04:05")
		AccesstimeFrom, ok1 := param["accesstimefrom"]
		AccesstimeTo, ok2 := param["accessstimeto"]
		if ty == 2 && ok1 != false && ok2 != false {
			AccesstimeF, err := typeOfInt64(AccesstimeFrom)
			if err != nil {
				return nil, err
			}
			AccesstimeT, err := typeOfInt64(AccesstimeTo)
			if err != nil {
				return nil, err
			}
			beginTime = time.Unix(AccesstimeF, 0).Format("2006-01-02T15:04:05")
			endTime = time.Unix(AccesstimeT, 0).Format("2006-01-02T15:04:05")
		}
		AddPersonInfo := HaiKAddPerson{
			haiKPerson{
				EmployeeNo:      code,
				Name:            name,
				UserType:        uty,
				Gender:          sex,
				LocalUIRight:    false,
				MaxOpenDoorTime: 0,
				Valid: valid{
					Enable:    true,
					BeginTime: beginTime,
					EndTime:   endTime,
					TimeType:  "local",
				},
				DoorRight: "1",
				RightPlan: []rightPlan{{
					DoorNo:         1,
					PlanTemplateNo: "1",
				}},
				UserVerifyMode: "",
			},
		}
		send, err := json.Marshal(AddPersonInfo)
		if err != nil {
			return nil, errors.New("json marshal err:" + err.Error())
		}
		res, err := httpRequest(ip, POST, HaiKAddPersonUrl, send, username, password)
		if err != nil {
			return nil, errors.New("return fail:" + err.Error())
		}
		if gjson.Get(string(res), "statusCode").Int() != 1 {
			result[code] = false
			result["errcode"] = gjson.Get(string(res), "errorCode").Int()
			result["msg"] = gjson.Get(string(res), "subStatusCode").String()
			return result, nil
		}
		resPic, err := addPic(ip, HaiKPicture, img, code, username, password)
		if err != nil {
			d.delPerson(id, map[string]interface{}{code: code}, nil)
			return nil, errors.New("return picture fail:" + err.Error())
		}
		if gjson.Get(string(resPic), "statusCode").Int() == 1 {
			result[code] = true
		} else {
			result[code] = false
			d.delPerson(id, map[string]interface{}{code: code}, nil)
			result["errcode"] = gjson.Get(string(resPic), "errorCode").Int()
			result["msg"] = gjson.Get(string(resPic), "subStatusCode").String()
		}
	}
	return result, nil
}

type haiKDelPerson struct {
	UserInfoDelCond userInfoDelCond `json:"UserInfoDelCond"`
}

type userInfoDelCond struct {
	EmployeeNoList []employeeList `json:"EmployeeNoList"`
}

type employeeList struct {
	EmployeeNo string `json:"employeeNo"`
}

func (d *HaiKClient) delPerson(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	var employeeNoList []employeeList
	for _, employee := range params {
		employeeNoList = append(employeeNoList, employeeList{
			EmployeeNo: fmt.Sprintf("%v", employee),
		})
	}
	delPersonInfo := haiKDelPerson{
		UserInfoDelCond: userInfoDelCond{employeeNoList},
	}
	send, err := json.Marshal(delPersonInfo)
	if err != nil {
		return nil, errors.New("json marshal err:" + err.Error())
	}
	res, err := httpRequest(ip, PUT, HaiKDelPersonUrl, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	if gjson.Get(string(res), "statusCode").Int() == 1 {
		for _, employee := range employeeNoList {
			result[employee.EmployeeNo] = true
		}
	} else {
		for _, employee := range employeeNoList {
			result[employee.EmployeeNo] = false
		}
		result["errcode"] = gjson.Get(string(res), "errorCode").Int()
		result["msg"] = gjson.Get(string(res), "errorMsg").String()
	}
	return result, nil
}

type haiKQueryPerson struct {
	UserInfoSearchCond userInfoSearchCond `json:"UserInfoSearchCond"`
}

type userInfoSearchCond struct {
	SearchID             string `json:"searchID"`
	MaxResults           int    `json:"maxResults"`
	SearchResultPosition int    `json:"searchResultPosition"`
}

type queryPersonResponse struct {
	Code string `json:"code"`
	Name string `json:"name"`
	Type int    `json:"type"`
}

func (d *HaiKClient) queryPerson(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	HaiKParamsInfo := NewHaiKParams(params)
	limit, err := HaiKParamsInfo.GetInt8("limit")
	if err != nil {
		return nil, err
	}
	offset, err := HaiKParamsInfo.GetInt8("offset")
	if err != nil {
		return nil, err
	}
	uid := "searchPersonIdBy" + ip
	queryPersonInfo := haiKQueryPerson{
		UserInfoSearchCond: userInfoSearchCond{
			SearchID:             uid,
			MaxResults:           int(limit),
			SearchResultPosition: int(offset),
		},
	}
	send, err := json.Marshal(queryPersonInfo)
	if err != nil {
		return nil, errors.New("json marshal err:" + err.Error())
	}
	res, err := httpRequest(ip, POST, HaiKQueryPersonUrl, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	if gjson.Get(string(res), "UserInfoSearch.responseStatusStrg").String() == "OK" {
		users := gjson.Get(string(res), "UserInfoSearch.UserInfo").Array()
		for _, user := range users {
			ty, err := encodePersonType(user.Get("type").String())
			if err != nil {
				logger.Log.Error(err.Error())
				fmt.Println("ty is err:", err)
			}
			code := user.Get("employeeNo").String()
			name := user.Get("name").String()
			result[code] = queryPersonResponse{
				Code: code,
				Name: name,
				Type: int(ty),
			}
		}
	} else {
		return nil, errors.New("query fail")
	}
	return result, nil
}

type haiKAddCard struct {
	CardInfo cardInfo `json:"CardInfo"`
}

type cardInfo struct {
	EmployeeNo string `json:"employeeNo"`
	CardNo     string `json:"cardNo"`
	CardType   string `json:"cardType"`
}

func (d *HaiKClient) insertCard(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	HaiKParamsInfo := NewHaiKParams(params)
	cardId, err := HaiKParamsInfo.GetStr("id")
	if err != nil {
		return nil, err
	}
	code, err := HaiKParamsInfo.GetStr("code")
	if err != nil {
		return nil, err
	}
	Type, err := HaiKParamsInfo.GetInt8("type")
	if err != nil {
		return nil, err
	}
	var cardTy string
	switch Type {
	case 1:
		cardTy = "normalCard"
	case 2:
		cardTy = "hijackCard"
	default:
		return nil, errors.New("no this card type, please fill 1,2")
	}
	addCardInfo := haiKAddCard{
		CardInfo: cardInfo{
			EmployeeNo: code,
			CardNo:     cardId,
			CardType:   cardTy,
		},
	}
	send, err := json.Marshal(addCardInfo)
	if err != nil {
		return nil, errors.New("json marshal err:" + err.Error())
	}
	res, err := httpRequest(ip, POST, HaiKInsertCardUrl, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	if gjson.Get(string(res), "statusCode").Int() == 1 {
		result["result"] = true
	} else {
		result["result"] = false
	}
	return result, nil
}

type haiKDelCard struct {
	CardInfoDelCond cardInfoDelCond `json:"CardInfoDelCond"`
}

type cardInfoDelCond struct {
	CardNoList []haiKCard `json:"CardNoList"`
}

type haiKCard struct {
	CardNo string `json:"cardNo"`
}

func (d *HaiKClient) delCard(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	HaiKParamsInfo := NewHaiKParams(params)
	cardId, err := HaiKParamsInfo.GetStr("id")
	if err != nil {
		return nil, err
	}
	delCardInfo := haiKDelCard{
		CardInfoDelCond: cardInfoDelCond{
			CardNoList: []haiKCard{
				{
					cardId,
				},
			},
		},
	}
	send, err := json.Marshal(delCardInfo)
	if err != nil {
		return nil, errors.New("json marshal err:" + err.Error())
	}
	res, err := httpRequest(ip, PUT, HaiKDelCardUrl, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	if gjson.Get(string(res), "statusCode").Int() == 1 {
		result["result"] = true
	} else {
		result["result"] = false
	}
	return result, nil
}

type haiKQueryCard struct {
	CardInfoSearchCond cardInfoSearchCond `json:"CardInfoSearchCond"`
}

type cardInfoSearchCond struct {
	SearchID             string `json:"searchID"`
	MaxResults           int    `json:"maxResults"`
	SearchResultPosition int    `json:"searchResultPosition"`
	EmployeeNoList       []employeeList
}

type queryCardResponse struct {
	ID         string `json:"id"`
	Type       int    `json:"type"`
	PersonCode string `json:"personCode"`
}

func (d *HaiKClient) queryCard(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	HaiKParamsInfo := NewHaiKParams(params)
	personId, _ := HaiKParamsInfo.GetStr("personcode")
	limit, err := HaiKParamsInfo.GetInt8("limit")
	if err != nil {
		return nil, err
	}
	offset, err := HaiKParamsInfo.GetInt8("offset")
	if err != nil {
		return nil, err
	}
	queryInfo := haiKQueryCard{
		CardInfoSearchCond: cardInfoSearchCond{
			SearchID:             "searchCardIdBy" + ip,
			MaxResults:           int(limit),
			SearchResultPosition: int(offset),
			EmployeeNoList: []employeeList{
				{EmployeeNo: personId},
			},
		},
	}
	send, err := json.Marshal(queryInfo)
	if err != nil {
		return nil, errors.New("json marshal err:" + err.Error())
	}
	res, err := httpRequest(ip, PUT, HaiKQueryCardUrl, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	if gjson.Get(string(res), "CardInfoSearch.responseStatusStrg").String() == "OK" {
		users := gjson.Get(string(res), "CardInfoSearch.CardInfo").Array()
		for _, user := range users {
			var ty int
			switch user.Get("type").String() {
			case "normalCard":
				ty = 1
			case "hijackCard":
				ty = 2
			}
			card := user.Get("cardNo").String()
			personCode := user.Get("employeeNo").String()
			result[card] = queryCardResponse{
				ID:         card,
				PersonCode: personCode,
				Type:       ty,
			}
		}
	} else {
		return nil, errors.New("query fail")
	}
	return result, nil
}

func (d *HaiKClient) open(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	//HaiKParamsInfo := NewHaiKParams(params)
	type RemoteControlDoor struct {
		Xmlns   string `xml:"xmlns,attr"`
		Version string `xml:"version,attr"`
		Cmd     string `xml:"cmd"`
	}
	controlDoor := RemoteControlDoor{
		Xmlns:   `http://www.isapi.org/ver20/XMLSchema`,
		Version: "2.0",
		Cmd:     "open",
	}
	send, err := xml.Marshal(controlDoor)
	res, err := httpRequest(ip, PUT, HaiKOpenDoor, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	fmt.Println(string(res))
	type Result struct {
		StatusCode   int    `xml:"statusCode"`
		StatusString string `xml:"statusString"`
	}
	resxml := Result{}
	err = xml.Unmarshal(res, &resxml)
	if err != nil {
		fmt.Println("err:", err)
	}
	if resxml.StatusCode == 1 {
		result["result"] = true
	} else {
		result["result"] = false
		return result, errors.New("open door fail!" + resxml.StatusString)
	}
	return result, nil
}

func (d *HaiKClient) close(id string, params map[string]interface{}, arrayParams []map[string]interface{}) (map[string]interface{}, error) {
	var result = make(map[string]interface{})
	thingInfo, err := cache.GetThing(id)
	if err != nil {
		return nil, errors.New("this dev is not exist")
	}
	ip := thingInfo.GetThingParam("IP", "")
	username := thingInfo.GetThingParam("username", "")
	password := thingInfo.GetThingParam("password", "")
	//HaiKParamsInfo := NewHaiKParams(params)
	type RemoteControlDoor struct {
		Xmlns   string `xml:"xmlns,attr"`
		Version string `xml:"version,attr"`
		Cmd     string `xml:"cmd"`
	}
	controlDoor := RemoteControlDoor{
		Xmlns:   `http://www.isapi.org/ver20/XMLSchema`,
		Version: "2.0",
		Cmd:     "close",
	}
	send, err := xml.Marshal(controlDoor)
	res, err := httpRequest(ip, PUT, HaiKCloseDoor, send, username, password)
	if err != nil {
		return nil, errors.New("return fail:" + err.Error())
	}
	fmt.Println(string(res))
	type Result struct {
		StatusCode   int    `xml:"statusCode"`
		StatusString string `xml:"statusString"`
	}
	resxml := Result{}
	err = xml.Unmarshal(res, &resxml)
	if err != nil {
		fmt.Println("err:", err)
	}
	if resxml.StatusCode == 1 {
		result["result"] = true
	} else {
		result["result"] = false
		return result, errors.New("open door fail!" + resxml.StatusString)
	}
	return result, nil
}

func httpRequest(ip, method string, url string, params []byte, username, password string) ([]byte, error) {
	ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
	var buff bytes.Buffer
	buff.Write(params)
	request, err := http.NewRequest(method, `http://`+ip+url, &buff)
	if err != nil {
		return nil, err
	}
	err = httpAuthClient.ApplyHttpDigestAuth(username, password, `http://`+ip+url, request)
	request.WithContext(ctx)
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	//request.SetBasicAuth(username, password)
	if err != nil {
		return nil, err
	}
	resp, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func Base64Encoding(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

func Base64Decode(str string) []byte {
	decoded, _ := base64.StdEncoding.DecodeString(str)
	return decoded
}

//解密ase128
func aESDecrypt(crypted, key []byte) []byte {
	block, _ := aes.NewCipher(key)
	blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	origData = pKCS7UnPadding(origData)
	return origData
}

//去补码
func pKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:length-unpadding]
}

//加密ase128
func AESEncrypt(origData, key []byte) []byte {
	//获取block块
	block, _ := aes.NewCipher(key)
	//补码
	origData = pKCS7Padding(origData, block.BlockSize())
	//加密模式，
	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	//创建明文长度的数组
	crypted := make([]byte, len(origData))
	//加密明文
	blockMode.CryptBlocks(crypted, origData)
	return crypted
}

//补码
func pKCS7Padding(origData []byte, blockSize int) []byte {
	//计算需要补几位数
	padding := blockSize - len(origData)%blockSize
	//在切片后面追加char数量的byte(char)
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(origData, padtext...)
}

var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
	return quoteEscaper.Replace(s)
}

func addPic(ip, uri, filePath, eno, username, password string) ([]byte, error) {
	payload := &bytes.Buffer{}
	//创建一个multipart类型的写文件
	writer := multipart.NewWriter(payload)
	err := writer.WriteField("FaceDataRecord", fmt.Sprintf(`{"faceLibType":"blackFD","FDID":"1","FPID":"%s"}`, eno))
	if err != nil {
		fmt.Println("err:", err)
	}
	file, err := os.Open(filePath)
	defer file.Close()
	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition",
		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
			escapeQuotes("img"), escapeQuotes(filePath)))
	h.Set("Content-Type", "image/jpeg")
	part, err := writer.CreatePart(h)
	//part, err := writer.CreateFormFile("img", filePath)
	_, err = io.Copy(part, file)
	if err != nil {
		fmt.Println(err)
		return nil, errors.New("copy img file err:" + err.Error())
	}
	err = writer.Close()
	if err != nil {
		fmt.Println(err)
		return nil, errors.New("close file err:" + err.Error())
	}
	req, err := http.NewRequest(PUT, `http://`+ip+uri, payload)
	if err != nil {
		fmt.Println(err)
		return nil, errors.New("creat new request err:" + err.Error())
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	err = httpAuthClient.ApplyHttpDigestAuth(username, password, `http://`+ip+uri, req)
	if err != nil {
		return nil, errors.New("digest err:" + err.Error())
	}
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, errors.New("creat new request err:" + err.Error())
	}
	var b []byte
	b, err = ioutil.ReadAll(resp.Body)
	fmt.Println(string(b))
	return b, nil
}

func decodePersonType(ty int8) (string, error) {
	switch ty {
	case 1:
		return "normal", nil
	case 2:
		return "visitor", nil
	case 3:
		return "blackList", nil
	default:
		return "", errors.New("user type is not exist: please select 1,2,3 ")
	}
}

func encodePersonType(tname string) (int8, error) {
	switch tname {
	case "normal":
		return 1, nil
	case "visitor":
		return 2, nil
	case "blackList":
		return 3, nil
	default:
		return 0, errors.New("user type name is not exist: please select normal,visitor,blackList ")
	}
}

type HaiKParams struct {
	params map[string]interface{}
}

func NewHaiKParams(params map[string]interface{}) HaiKParams {
	return HaiKParams{params}
}

func (p HaiKParams) GetInt(key string) (int, error) {
	value, ok := p.params[key].(int)
	if ok {
		return value, nil
	} else {
		return 0, errors.New("this param is not exist:" + key)
	}
}

func (p HaiKParams) GetStr(key string) (string, error) {
	value, ok := p.params[key].(string)
	if ok {
		return value, nil
	} else {
		return "", errors.New("this param is not exist:" + key)
	}
}

func (p HaiKParams) GetInt8(key string) (int8, error) {
	value, ok := p.params[key].(int8)
	if ok {
		return value, nil
	} else {
		return 0, errors.New("this param is not exist:" + key)
	}
}

var haiKMg = make(map[string]string)

func HaiKRegister(id, brand string) {
	r := gin.Default()
	if _, ok := haiKMg[brand]; !ok {
		haiKMg[brand] = id
	}
	r.POST("/", HaiKHttpSv)
	fmt.Println(r.Run(":9090"))
}

func HaiKUnRegister(id string) {
	delete(haiKMg, id)
}

func HaiKHttpSv(c *gin.Context) {
	fmt.Println(c)
	id, ok := haiKMg[HaiKBrand]
	if !ok {
		logger.Log.Error("HaiK dev is not register")
		return
	}
	var msg string
	res, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		fmt.Println("err:", err)
	}
	msg = string(res)
	upTime, err := time.ParseInLocation("2006-01-02T15:04:05", gjson.Get(msg, "dateTime").String(), time.Local)
	if err != nil {
		fmt.Println("time is err:", err)
	}
	now := upTime.Unix()
	event := gjson.Get(msg, "AccessControllerEvent").String()
	params := make(map[string]interface{})
	params["now"] = now
	params["Name"] = gjson.Get(event, "name").String()
	if gjson.Get(event, "majorEventType").Int() == 5 {
		if gjson.Get(event, "subEventType").Int() == 75 {
			params["pin"] = gjson.Get(event, "employeeNoString").String()
			params["Event"] = "人脸认证成功"
		}
		if gjson.Get(event, "subEventType").Int() == 21 {
			notify.RawData(id, "rtstate", "", 0, 2, now, now)
			params["result"] = "开"
			params["Mod"] = "开"
		} else if gjson.Get(event, "subEventType").Int() == 22 {
			notify.RawData(id, "rtstate", "", 0, 1, now, now)
			params["result"] = "关"
			params["Mod"] = "关"
		}
		if no := gjson.Get(event, "employeeNoString").String(); no != "" {
			notify.RawData(id, "pin", "", 0, no, now, now)
			params["pin"] = no
		}
		notify.RawEvent(id, "guardLog", time.Now(), params, nil)
	}

}
